package me.spring.cloud.common.components.util.system;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.regex.Pattern;
import sun.net.util.IPAddressUtil;

/**
 * 网络工具
 */
public abstract class LocalAddressUtil {
  /**
   * 预先加载
   */
  public static InetAddress localAddress;

  static {
    try {
      localAddress = getLocalInetAddress();
    } catch (SocketException e) {
      throw new RuntimeException("fail to get local ip.");
    }
  }

  /**
   * 获取第一个IP地址
   *
   * @Return 第一个IP地址
   * @throws SocketException 网络异常
   */
  public static InetAddress getLocalInetAddress() throws SocketException {
    // enumerates all network interfaces
    Enumeration<NetworkInterface> enu = NetworkInterface.getNetworkInterfaces();
    while (enu.hasMoreElements()) {
      NetworkInterface ni = enu.nextElement();
      if (ni.isLoopback()) {
        continue;
      }
      Enumeration<InetAddress> addressEnumeration = ni.getInetAddresses();
      while (addressEnumeration.hasMoreElements()) {
        InetAddress address = addressEnumeration.nextElement();
        // ignores all invalidated addresses
        if (address.isLinkLocalAddress() || address.isLoopbackAddress() || address.isAnyLocalAddress()) {
          continue;
        }
        return address;
      }
    }
    throw new RuntimeException("No validated local address!");
  }

  /**
   * 获取IP
   *
   * @Return IP地址
   */
  public static String getLocalAddress() {
    return localAddress.getHostAddress();
  }

  /**
   * 获取第2段和第4段ip，并合并成4位,用于特殊场景下的ip特征
   *
   * @Return the string local address
   */
  public static String getLocalAddressParts() {
    String address = localAddress.getHostAddress();
    String[] parts = address.split("\\.");
    String second;
    String fourth;
    if (parts == null || parts.length == 0) {
      //under Wifi, ip is like:2001:0:9d38:6ab8:1444:650a:8b18:44a6
      String[] partsWifi = address.split(":");
      second = partsWifi[1].substring(0, 1);
      fourth = partsWifi[3].substring(0, 1);
    } else {
      second = parts[1];
      fourth = parts[3];
    }
    second = second.length() >= 3 ? second.substring(0, 2) : second;
    fourth = fourth.length() >= 3 ? fourth.substring(0, 2) : fourth;
    return second + fourth;
  }

  /**
   * @Return boolean
   * @Author luffy
   * @Description 验证ip是否是外网
   * @Date 2019-05-22 14:02
   * @Param [ip]
   **/
  public static boolean internalIp(String ip) {
    if(!IPAddressUtil.isIPv4LiteralAddress(ip)) {
      return false;
    }
    byte[] addr = IPAddressUtil.textToNumericFormatV4(ip);
    return internalIp(addr);
  }

  private static boolean internalIp(byte[] addr) {
    final byte b0 = addr[0];
    final byte b1 = addr[1];
    //10.x.x.x/8
    final byte SECTION_1 = 0x0A;
    //172.16.x.x/12
    final byte SECTION_2 = (byte) 0xAC;
    final byte SECTION_3 = (byte) 0x10;
    final byte SECTION_4 = (byte) 0x1F;
    //192.168.x.x/16
    final byte SECTION_5 = (byte) 0xC0;
    final byte SECTION_6 = (byte) 0xA8;
    switch (b0) {
      case SECTION_1:
        return false;
      case SECTION_2:
        if (b1 >= SECTION_3 && b1 <= SECTION_4) {
          return false;
        }
      case SECTION_5:
        if (b1 == SECTION_6) {
          return false;
        }
      default:
        return true;

    }
  }
}